package com.apobates.forum.orize.core.plug;

import com.apobates.forum.orize.core.OrizeSlotResourceMatchStrategy;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;

/**
 * 一般性占位资源匹配策略
 * 支持: ${占位符}和{占位符}
 * @author xiaofanku@live.cn
 * @since 20210822
 */
public class OrizeSlotResourceMatchGeneralStrategy implements OrizeSlotResourceMatchStrategy {
    private final static Logger logger = LoggerFactory.getLogger(OrizeSlotResourceMatchGeneralStrategy.class);
    private final static String PATH_SPLIT="/";

    @Override
    public boolean match(String requestPath, String resourcePath, String resourceSlotsKey) {
        Map<String,String> map = extractSlotMap(requestPath, resourcePath);
        if(!map.isEmpty()){ //有提取到占位符了
            List<String> definedKeys = Arrays.asList(resourceSlotsKey.split(","));
            //计算交集
            Set<String> definedKeySet = new HashSet<>(definedKeys);
            Set<String> matchKeys = map.keySet();
            //从定义中--->匹配到的
            definedKeySet.retainAll(matchKeys);
            //
            return (definedKeys.size() == definedKeySet.size());
        }
        return false;
    }

    /**
     * 根据资源定义中的路径提取请求路径中占位信息
     *
     * @param reqURL 请求路径
     * @param resURL 资源定义中的路径
     * @return 无法提取返回空集合
     */
    protected static Map<String,String> extractSlotMap(String reqURL, String resURL){
        String[] reqSlots = reqURL.split(PATH_SPLIT);
        String[] resSlots = resURL.split(PATH_SPLIT);
        //两者的长度不一致退出
        if(reqSlots.length != resSlots.length){
            return Collections.emptyMap();
        }
        Map<String,String> data = new HashMap<>();
        for(int i=0;i<resSlots.length;i++){
            //中间量
            String[] tmp = clearSlotSegment(resSlots[i], reqSlots[i]);
            if(tmp[0].equalsIgnoreCase(tmp[1])){ //这一段相同
                continue;
            }else{
                //是否resSlots[i]以占符标识开头
                if(tmp[0].startsWith("{") || tmp[0].startsWith("${")){
                    //定义需要替换掉的占位符符号
                    String[] slotChar = {"${", "{", "}"}, wplace={"","",""};
                    StringUtils.replaceEach(tmp[0], slotChar,wplace);
                    String _phChar = StringUtils.replaceEach(tmp[0], slotChar,wplace);
                    data.put(_phChar, tmp[1]);
                }else{
                    return data;
                }
            }
        }
        if(logger.isDebugEnabled()) {
            logger.debug("======================RM======================");
            data.entrySet().stream().forEach(entry -> {
                logger.debug("slotKey:" + entry.getKey() + ", slotVal:" + entry.getValue());
            });
            logger.debug("======================RM======================");
        }
        return data;
    }

    /**
     * 清洗Slot Segment
     * @param resSlotVar 资源路径的Segment
     * @param reqSlotVar 请求路径的Segment
     * @return 0=清洗后的资源Segment,1=清洗后的靖求Segment
     */
    protected static String[] clearSlotSegment(String resSlotVar, String reqSlotVar){
        //中间量
        String tmpResSeg = resSlotVar, tmpReqSeg=reqSlotVar;
        //是否包含扩展名,包含的话清理掉它
        int dotPos = resSlotVar.lastIndexOf(".");
        if(dotPos>0){
            //扩展名一样吗?
            String extName = resSlotVar.substring(dotPos);
            if(reqSlotVar.endsWith(extName)) {
                tmpResSeg = resSlotVar.substring(0, dotPos);
                tmpReqSeg = reqSlotVar.substring(0, reqSlotVar.indexOf("."));
            }
        }
        return new String[]{tmpResSeg, tmpReqSeg};
    }
}
